package com.dy.design_pattern_study.composite_pattern.dome2;

import com.dy.design_pattern_study.composite_pattern.dome2.impl.ConcreteCompany;
import com.dy.design_pattern_study.composite_pattern.dome2.impl.FinanceDepartment;
import com.dy.design_pattern_study.composite_pattern.dome2.impl.HRDepartment;

/**
 * @CreateBy zhangdingyi
 * @Date 2023-04-12
 * @Content
 * 组合模式（Composite），将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
 *
 * 简单的说，组合模式实质就是子节点增加，在有一个接口的前提下，声明根节点，其他的都是子节点
 * 就是声明一个A A可以添加 A1 A2 这种叶子，也可以添加 B 这种树枝 B 又可以添加 B1 B2 以此类推
 *
 * 然后是关于 组合模式的两种设计
 * 透明模式和安全模式
 * 透明方式，也就是说在Component中声明所有用来管理子对象的方法，其中包括Add、Remove等。
 * 这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别，它们具备完全一致的行为接口。
 * 但问题也很明显，因为Leaf类本身不具备Add()、Remove()方法的功能，所以实现它是没有意义的
 *--简单的讲透明模式实质就是 抽象父类 包含着 所有的通用方法，不管实际上子类是否用到
 *
 * 安全方式，也就是在Component接口中不去声明Add和Remove方法，那么子类的Leaf也就不需要去实现它，
 * 而是在Composite声明所有用来管理子类对象的方法，这样做就不会出现刚才提到的问题，
 * 不过由于不够透明，所以树叶和树枝类将不具有相同的接口，客户端的调用需要做相应的判断，带来了不便。
 *--简单的讲安全方式就是，父类仅包含子类通用且都实际使用的方法，不其他的方法根据子类的实际来具体添加
 *
 * 什么地方用组合模式比较好呢？
 * 1.需求中是体现部分与整体层次的结构时，以及你希望用户可以忽略组合对象与单个对象的不同，统一地使用组合结构中的所有对象时，就应该考虑用组合模式了
 *
 * 组合模式的优势。
 * 1.组合模式这样就定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对象的类层次结构。
 * 基本对象可以被组合成更复杂的组合对象，而这个组合对象又可以被组合，
 * 这样不断地递归下去，客户代码中，任何用到基本对象的地方都可以使用组合对象了
 * 灵活的使用和体现，组合对象和层次结构
 * 2.用户是不用关心到底是处理一个叶节点还是处理一个组合组件，也就用不着为定义组合而写一些选择判断语句了。
 * 组合模式让客户可以一致地使用组合结构和单个对象。
 *
 */
public class client {
    public static void main(String[] args) {

        //总公司 -- 一级节点
        ConcreteCompany root = new ConcreteCompany("北京总公司");
        //总公司下级 -- 二级节点
        root.add(new HRDepartment("总公司人力资源部"));
        root.add(new FinanceDepartment("总公司财务部"));

        //分公司 -- 二级节点
        ConcreteCompany comp = new ConcreteCompany("上海华东分公司");

        //分公司下级 -- 三级节点
        comp.add(new HRDepartment("华东分公司人力资源部"));
        comp.add(new FinanceDepartment("华东分公司财务部"));
        root.add(comp);

        //办事处 -- 三级节点
        ConcreteCompany comp1 = new ConcreteCompany("南京办事处");

        //办事处下级 -- 四级节点
        comp1.add(new HRDepartment("南京办事处人力资源部"));
        comp1.add(new FinanceDepartment("南京办事处财务部"));
        comp.add(comp1);

        //办事处 -- 三级节点
        ConcreteCompany comp2 = new ConcreteCompany("杭州办事处");

        //办事处下级 -- 四级节点
        comp2.add(new HRDepartment("杭州办事处人力资源部"));
        comp2.add(new FinanceDepartment("杭州办事处财务部"));
        comp.add(comp2);

        System.out.println("\n结构图：");
        root.display(1);
        System.out.println("\n职责：");
        root.lineOfDuty();
    }
}
